(let* ([address-info (car (getaddrinfo "www.gnu.org" "http"))]
       [an-input-socket
        (socket (addrinfo:fam address-info)  ; IPv4 or IPv6
                         (addrinfo:socktype address-info)  ; ???
                         (addrinfo:protocol address-info)  ; HTTP etc
                         )])
  (setvbuf an-input-socket 'line)
  (connect an-input-socket (addrinfo:addr address-info))
  an-input-socket)

(catch 'getaddrinfo-error
  (lambda ()
    (getaddrinfo "www.gnu.org" "gopher"))
  (lambda (key errcode)
    (cond ((= errcode EAI_SERVICE)
           (display "doesn't know about Gopher!\n"))
          ((= errcode EAI_NONAME)
           (display "www.gnu.org not found\\n"))
          (else
           (format #t "something wrong: ~a\n"
                   (gai-strerror errcode))))))

;; =======================================
;; EXAMPLE USING INTERNET SOCKETS (SERVER)
;; =======================================

(let ([s (socket PF_INET SOCK_STREAM 0)])
  ;; setsockopt socket level option-name value
  (setsockopt s SOL_SOCKET SO_REUSEADDR 1)
  ;; Specific address?

  ;; bind the socket to:
  ;; a port (2904),
  ;; a protocol family (AF_INET),
  ;; and an incoming addresses (INADDR_ANY) – (all available interfaces?)
  ;; (bind s AF_INET (inet-pton AF_INET "127.0.0.1") 2904)
  (bind s AF_INET INADDR_ANY 12345)

  ;; enable the port to listen
  ;; maximum queue of incoming connections is 5
  (listen s 5)

  (simple-format #t "Listening for clients in pid: ~S" (getpid))
  (newline)

  ;; loop for getting messages
  (while #t
    (let* ((client-connection (accept s))
           (client-details (cdr client-connection))
           (client (car client-connection)))
      (simple-format #t
                     "Got new client connection: ~S"
                     client-details)
      (newline)
      (simple-format #t
                     "Client address: ~S"
                     (gethostbyaddr (sockaddr:addr client-details)))
      (newline)
      ;; Send back the greeting to the client port
      (display "Hello client\r\n" client)
      (close client))))




;; =====================================
;; LISTENING ON A PORT – MAKING A SERVER
;; =====================================


;; 1. MAKE A SOCKET

;; 2. BIND PORT TO AN ADDRESS

;; Scheme Procedure: bind sock sockaddr
;; Scheme Procedure: bind sock AF_INET ipv4addr port
;; Scheme Procedure: bind sock AF_INET6 ipv6addr port [flowinfo [scopeid]]
;; Scheme Procedure: bind sock AF_UNIX path

(bind sock        ; the socket with which we will work to get stuff we listen for
      AF_INET     ; IPv4
      INADDR_ANY  ; allow inbound from everywhere
      12345))     ; listen on port 12345

;; ALTERNATiVELY

(bind sock
      (make-socket-address AF_INET
                           INADDR_ANY
                           12345))

;; 3. ENABLE SOCKET TO ACCEPT CONNECTION REQUESTS
(let ([backlog-of-connection-requests 10])
  (listen sock backlog-of-connection-requests))

;; 4. ACCEPT A CONNECTION
;; "flags, if given, may include sock_cloexec or sock_nonblock,
;; which like o_cloexec and o_nonblock apply to the newly accepted socket. "
;; (accept sock [flags])

;; A socket cannot by used for communication until it has been connected somewhere,
;;  usually with either connect (client) or accept (server).
(accept sock)

;; ===================================
;; CONNECT TO A PORT – MAKING A CLIENT
;; ===================================

;; 1. MAKE A SOCKET

;; PF = protocol family?
(socket PF_INET 0 (protoent:proto (getprotobyname "TCP")))

;; 2. CONNECT TO ADDRESS

;; Scheme Procedure: connect sock sockaddr
;; Scheme Procedure: connect sock AF_INET ipv4addr port
;; Scheme Procedure: connect sock AF_INET6 ipv6addr port [flowinfo [scopeid]]
;; Scheme Procedure: connect sock AF_UNIX path
(connect sock AF_INET INADDR_LOOPBACK 23)
(connect sock (make-socket-address AF_INET INADDR_LOOPBACK 23))

;; ======================
;; SHUTDOWN COMMUNICATION
;; ======================

;; values for `how`:
;; 0: Stop receiving data for this socket. If further data arrives, reject it.
;; 1: Stop trying to transmit data from this socket. Discard any data waiting to be sent. Stop looking for acknowledgement of data already sent; don’t retransmit it if it is lost.
;; 2 Stop both reception and transmission.
(shutdown sock 0)
(shutdown sock 1)
(shutdown sock 2)
